//***************************************************************************
// Class: Queue
//
// Written By: Stephen Durfey 
//
// For: CS 202 MWF 9:30am-10:20am
//
// Instructor: Ron Conway
//
// Included Files:
//
//	iostream.h
//	queue.h	
//
//
//***************************************************************************

#include<iostream>
#include"queue.h"
using namespace std;

//***************************************************************************
//
// NAME OF FUNCTION: Copy Constructor
//
// PURPOSE: creates a copy of an exixting object for call-by-value
//
// PARAMETERS: Queue object (must be by reference)
//
// RETURN VALUE: None

// CALLS TO: enqueue and dequeue
//
// CALLED FROM: client and class (indirectly)
//
// METHOD: I wonder if you even read this stuff.
//
//
//***************************************************************************

Queue::Queue(const Queue &init)
{
	QueueNode *Tptr = init.ptrFront;
	ptrFront = ptrRear= NULL;

	while (Tptr)
	{	
		(*this).enqueue(Tptr->NumItems);
		Tptr = Tptr->next;
	}
}

//***************************************************************************
//
// NAME OF FUNCTION: Destructor
//
// PURPOSE: destroys the nodes in the queue before it goes out of scope
//
// PARAMETERS: Pointer to the head of the queue.
//
// RETURN VALUE: None

// CALLS TO: RemoveQueue
//
// CALLED FROM: client (indirectly)
//
// METHOD: I wonder if you even read this stuff.
//
//
//***************************************************************************

Queue::~Queue()
{
	RemoveQueue();
}


//***************************************************************************
//
// NAME OF FUNCTION: Operator=
//
// PURPOSE: overloads the = operator.
//
// PARAMETERS: Queue object (must be by reference)
//
// RETURN VALUE: None

// CALLS TO: RemoveQueue, enqueue
//
// CALLED FROM: client and class (indirectly)
//
// METHOD: I wonder if you even read this stuff.
//
//
//***************************************************************************

Queue &Queue::operator=(const Queue &rightObj)
{
	QueueNode *Tptr = rightObj.ptrFront;

    if ( this != &rightObj)
    {   (*this).RemoveQueue();

	    while (Tptr)
	    {	(*this).enqueue(Tptr->NumItems);
		    Tptr = Tptr->next;
	    }
    }

	return *this;
}
//***************************************************************************
//
// NAME OF FUNCTION: isEmpty()
//
// PURPOSE: to see if the Queue is empty
//
// PARAMETERS: None
//
// RETURN VALUE: 1 if empty, 0 if not empty
//
// CALLS TO: none
//
// CALLED FROM: client, pop
//
// METHOD: checks to see if the front pointer is 0.
//
//
//***************************************************************************

bool Queue::isEmpty()
{
	if(ptrFront)
		return false;
	else
		return true;
}

//***************************************************************************
//
// NAME OF FUNCTION: RemoveQueue()
//
// PURPOSE: deletes the nodes while traverse the list
//
// PARAMETERS: Pointer to the first Node in the queue
//
// RETURN VALUE: 1 if empty, 0 if not empty
//
// CALLS TO: none
//
// CALLED FROM: destructor, operator=
//
// METHOD: I love to rock and roll all night...and party every day!
//
//
//***************************************************************************
void Queue::RemoveQueue()
{
		QueueNode *Dptr = ptrFront;
        while(ptrFront)             // while list is not empty
        {
           ptrFront = ptrFront->next;   // move head pointer
           delete Dptr;              // delete node
           Dptr = ptrFront;            // copy head pointer
        }
}

/*************************************************************************
* Function Name: enqueue												 *
*																		 *
* Purpose: adds items into the checkout line queue						 *
*																		 *
* Parameters: int item which contains the integer value of the items to  *
*             be added into the queue.									 *
*																		 *
* Calls: isEmpty(), this is to determine if the queue is empty, if it is *
*        then ptrFront and ptrRear are both assigned to its position in  *
*        memory. If it is not, then ptrRear->next is assigned to the     *
*	     next node in the list.											 *
*																		 *
* Called From: operator+=(Queue &Qobj)									 *
*************************************************************************/

void Queue::enqueue(int item)
{
	if(isEmpty())
	{
		ptrFront = ptrRear = new QueueNode(item);
	}
	else
	{
		ptrRear->next = new QueueNode(item);
		ptrRear = ptrRear->next;
	}
}

/*************************************************************************
* Function Name: dequeue												 *
*																		 *
* Purpose: deletes items into the checkout line queue				     *
*																		 *
* Parameters: int item which contains the integer value of the items to  *
*             be added into the queue, is passed by reference. It is     *
              passed this way to return the integer value back to its    *
			  calling function, operator--(), for later printout		 *
*																		 *
* Calls: isEmpty(), this is to determine if the queue is empty, if it    *
*		 is not, then the first node is removed from the queue and       *
*		 program control is returned to operator--(). if the queue is    *
*		 empty, then nothing happens.									 *
*																		 *
* Called From: operator--()              								 *
*************************************************************************/

void Queue::dequeue(int &item)
{
	QueueNode* Tptr;
	
	if(!isEmpty())
	{
		Tptr = ptrFront;
		item = Tptr->NumItems;
		ptrFront = Tptr->next;
		delete Tptr;
	}
}

/*************************************************************************
* Function Name: operator--												 *
*																		 *
* Purpose: overloads the -- operator to remove a customer from the 		 *
*          grocery line.												 *
*																		 *
* Parameters: none                  									 *
*																		 *
* Calls: none															 *
*																		 *
* Called From: client program											 *
*************************************************************************/

Queue &Queue::operator --()
{
	int item;

	dequeue(item);

	if(!isEmpty()) //ensures the line is not empty before printing out the items
		cout << item << " ";

	return *this;
}

/*************************************************************************
* Function Name: operator+=  											 *
*																		 *
* Purpose: overloads the += operator to work with our class. It is used	 *
	       to add a number of items to the line queue that is passed     *
		   to it from the client program.
*																		 *
* Parameters: int item which contains the integer value of the items to  *
*             be added into the queue.									 *
*																		 *
* Calls: enqueue to add the items to the queue							 *
*																		 *
* Called From: client													 *
*************************************************************************/

Queue &Queue::operator +=(int items)
{
	enqueue(items);
	return *this;
}

/*************************************************************************
* Function Name: operator+=  											 *
*																		 *
* Purpose: overloads the += operator to work with our class. It is used	 *
	       to combine one Line with another Line.						 *			
*																		 *
* Parameters: Queue &Qobj; this is the line that will be added to the    *
              the implied Line											 *
*																		 *
* Calls: nothing														 *
*																		 *
* Called From: client													 *
* Returns: *this, the implied object									 *
* Method: the function receives an object from the client program and    *
*		  function checks the following conditions: if neither the		 *
*		  implied object nor the explicit object are empty then		     *
*		  the queue of the implied object is expanded to include the     *
*		  queue of the explicit object; if the implied object is empty   *
*		  and the explicit object is not, then the implied object is set *
*		  to include just the explicit objects' queue. if both are empty *
*		  then nothing happens. by default all the explicit object is    *
*		  set to NULL.													 *
*************************************************************************/

Queue &Queue::operator +=(Queue &Qobj)
{
	if(!isEmpty() && !Qobj.isEmpty())
	{
		ptrRear->next = Qobj.ptrFront;
		ptrRear = Qobj.ptrRear;
	}
	else if(isEmpty() && !Qobj.isEmpty())
	{
		ptrFront = Qobj.ptrFront;
		ptrRear = Qobj.ptrRear;
	}

	Qobj.ptrFront = Qobj.ptrRear = NULL;

	return *this;
}

/*************************************************************************
* Function Name: operator+  											 *
*																		 *
* Purpose: overloads the + operator to work with our class. It is used	 *
	       to combine one Line with another Line. This new Line is 		 *			
		   stored in Temp object. This Temp object just has its pointers *
		   assigned to the front of Line1 and the rear of Line2.         *
		   After the new Line has been created the front and rear        *
		   pointers from both the implied and explicit object are set    *
		   to NULL;
*																		 *
* Parameters: Queue &Qobj; this is the line that will be added to the    *
              the implied Line											 *
*																		 *
* Calls: nothing														 *
*																		 *
* Called From: client													 *
* Returns: Temp, the temp Queue object created							 *
* Method:  receives an object and checks the following conditions: if    *
*		   the implied object and the explicit object are not empty, then*
*		   it will rearrange the queue to include both objects in the    *
*		   temp object; if the implied object is not empty, but the      *
*		   explicit object is, then the temp object will just contain    *
*		   the implied object; if the explicit object is not empty, but  *
*		   the implied object is, then the temp object will contain      *
*		   just the explicit object. if both are empty then no values    *
*		   are changed and everything points to NULL.					 *
*************************************************************************/

Queue Queue::operator +(Queue &Qobj)
{
	Queue Temp;

	if(!isEmpty() && !Qobj.isEmpty())
	{
		Temp.ptrFront = ptrFront;
		Temp.ptrRear = ptrRear;
		Temp.ptrRear->next = Qobj.ptrFront;
		Temp.ptrRear = Qobj.ptrRear;
	}
	else if(!isEmpty() && Qobj.isEmpty())
	{
		Temp.ptrFront = ptrFront;
		Temp.ptrRear = ptrRear;
	}
	else if(isEmpty() && !Qobj.isEmpty())
	{
		Temp.ptrFront = Qobj.ptrFront;
		Temp.ptrRear = Qobj.ptrRear;
	}

	ptrFront = ptrRear = Qobj.ptrFront = Qobj.ptrRear = NULL;

	return Temp;
}

/*************************************************************************
* Function Name: operator < 											 *
*																		 *
* Purpose: overloads the < operator to work with our class. It is used	 *
	       to determine which Line object has more customers in its      *
		   queue. To determine this, two local variables are declared:   *
		   left and right. These will hold the total number of customers *
		   in each line.												 *
*																		 *
* Parameters: Queue &Qobj;   											 *
*																		 *
* Calls: nothing														 *
*																		 *
* Called From: client													 *
* Returns: either true or false depending on if left has more or less	 *
		   customers than right.										 *
*************************************************************************/

bool Queue::operator <(const Queue &Qobj)
{
	QueueNode* Tptr = ptrFront;
	int left = 0, right = 0;

	while(Tptr)
	{
		left++;
		Tptr = Tptr->next;
	}

	Tptr = Qobj.ptrFront;
	
	while(Tptr)
	{
		right++;
		Tptr = Tptr->next;
	}

	delete Tptr;

	if(left < right)
		return true;
	else
		return false;
}

/*************************************************************************
* Function Name: operator > 											 *
*																		 *
* Purpose: overloads the > operator to work with our class. It is used	 *
	       to determine which Line object has more customers in its      *
		   queue. To determine this, two local variables are declared:   *
		   left and right. These will hold the total number of customers *
		   in each line.												 *
*																		 *
* Parameters: Queue &Qobj;   											 *
*																		 *
* Calls: nothing														 *
*																		 *
* Called From: client													 *
* Returns: either true or false depending on if left has more or less	 *
		   customers than right.										 *
*************************************************************************/

bool Queue::operator >(const Queue &Qobj)
{
	QueueNode* Tptr = ptrFront;
	int left = 0, right = 0;

	while(Tptr)
	{
		left++;
		Tptr = Tptr->next;
	}

	Tptr = Qobj.ptrFront;
	
	while(Tptr)
	{
		right++;
		Tptr = Tptr->next;
	}

	delete Tptr;

	if(left > right)
		return true;
	else
		return false;
}

/*************************************************************************
* Function Name: operator<<										     	 *
*																		 *
* Purpose: overloads the << operator in the iostream library			 *
		   to work with our class. it accepts the insertion stream		 *
		   operator and an object. If object is empty, it prints out     *
		   "Empty Line", else it will tranverse the list and print out   *
		   the # of items for each customer in the queue				 *
*																		 *
* Parameters: ostream &output, Queue &Qobj;   							 *
*																		 *
* Calls: isEmpty()														 *
*																		 *
* Called From: client													 *
* Returns: the passed insertion stream operator to enable cascading		 *
*************************************************************************/

ostream &operator <<(ostream &output, Queue &Qobj)
{
	QueueNode* Tptr = Qobj.ptrFront;

	if(Qobj.isEmpty())
	{
		output << "Empty Line";
	}
	else
	{

		while(Tptr)
		{
			output << Tptr->NumItems << " ";
			Tptr = Tptr->next;
		}
	}

	delete Tptr;

	return output;
}







	








